package de.playmee;

import java.util.List;

import de.playmee.dialogs.ProgressWheelDialog;
import de.playmee.geo.GeoActivity;
import de.playmee.geo.Region;
import de.playmee.handler.ChannelHandler;
import de.playmee.handler.ChannelTrackRatingHandler;
import de.playmee.handler.PlaylistHandler;
import de.playmee.handler.RegionHandler;
import de.playmee.services.LoadingService;
import de.playmee.services.MusicService;
import de.playmee.services.LoadingService.DownloadTrackDataListener;
import de.playmee.tasks.ComputePlaylistTask;
import de.playmee.tasks.ComputePlaylistTask.PlaylistComputedListener;
import de.playmee.tasks.UpdateWeatherConditionsTask;
import de.playmee.tasks.UpdateWeatherConditionsTask.WeatherUpdatedListener;
import android.app.TabActivity;
import android.content.Intent;
import android.content.res.Resources;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.location.LocationProvider;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.widget.TabHost;
import android.widget.Toast;
import android.widget.TabHost.TabSpec;

@SuppressWarnings("deprecation")
public class MainActivity extends TabActivity implements PlaylistComputedListener {

	private final String TAG = "MainActivity";

	private Resources res;
	private TabHost tabHost;

	private final int UPDATE_TIME = 1000 * 30; // 30s

	public final int TAB_PLAYER = 0;
	public final int TAB_CHANNEL = 1;
	public final int TAB_MAP = 2;
	public final int TAB_RATING = 3;
	public final int TAB_DEFAULT = TAB_CHANNEL;
	
	private Playmee application;
	private ChannelHandler cHandler;
	private ChannelTrackRatingHandler ctrHandler;
	
	private ProgressWheelDialog progressWheelDialog;
	private Handler progressWheelHandler;

	/**
	 * called when the activity is first created
	 */
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.main);
		
		application = (Playmee) getApplication();
		cHandler = application.getChannelHandler();
		ctrHandler = application.getChannelTrackRatingHandler();
		
		progressWheelDialog = new ProgressWheelDialog(this);

		res = getResources();
		tabHost = getTabHost();

		createTabs();
		switchToDefaultTab();

		// create location listener to update the current location
		// and the current weather conditions
		((LocationManager) getSystemService(LOCATION_SERVICE))
				.requestLocationUpdates(LocationManager.GPS_PROVIDER,
						UPDATE_TIME, 0, new LocationListener() {
							@Override
							public void onLocationChanged(Location location) {
								// Toast.makeText(MainActivity.this, "GPS location:\nx = " + location.getLatitude() + "\ny = " + location.getLongitude(), Toast.LENGTH_SHORT).show();
								updateWeatherConditions(location);
								if (!application.isStartingChannelInRegion) {
									application.isStartingChannelInRegion = true;
									Region newRegion = getRegion(location);
									if (application.currentRegion != newRegion)
										playChannel(newRegion);
								}
							}

							@Override
							public void onProviderDisabled(String provider) {
								// nothing to do
								// Toast.makeText(MainActivity.this, "GPS location provider disabled.", Toast.LENGTH_LONG).show();
							}

							@Override
							public void onProviderEnabled(String provider) {
								// Toast.makeText(MainActivity.this, "GPS location provider enabled.", Toast.LENGTH_LONG).show();
								updateWeatherConditions(null);
							}

							@Override
							public void onStatusChanged(String provider, int status, Bundle extras) {
								// Toast.makeText(MainActivity.this, "GPS location provider status: " + status, Toast.LENGTH_LONG).show();
								if (status == LocationProvider.AVAILABLE)
									updateWeatherConditions(null);
							}
						});
		
		progressWheelHandler = new Handler() {
			@Override
			public void handleMessage(Message msg) {
				if (msg.what == 1) {
					progressWheelDialog.show();
				} else if (msg.what == 0) {
					progressWheelDialog.dismiss();
				}
			}
		};
		
		final List<Long> channelIds = cHandler.loadChannelIds(null, null, null, null);
		application.addDownloadTrackDataListener(new DownloadTrackDataListener() {
			@Override
			public void onSingleTrackDataDownloaded(Track track) {
				// insert channel-track-rating of this track for all channels
				long trackId = track.getIdDatabase();
				if (trackId > 0)
					ctrHandler.insertChannelTrackRatings(channelIds, trackId);
			}
			
			@Override
			public void onAllTracksDataDownloaded() {
				progressWheelHandler.sendEmptyMessage(1);
				
				// download ratings the user has already uploaded
				application.getMusicHandler().downloadAndAddMissingRatings();
				
				progressWheelHandler.sendEmptyMessage(0);
			}
		});

		startService(new Intent(LoadingService.ACTION_DOWNLOAD_TRACKDATA));
		startService(new Intent(LoadingService.ACTION_UPLOAD_TRACK));
	}

	/**
	 * creates all tabs
	 */
	private void createTabs() {
		Log.i(TAG, "Creating tabs...");

		Intent intent;
		int icon;

		// player
		icon = R.drawable.ic_tab_player;
		intent = new Intent().setClass(this, PlayerActivity.class);
		addNewTabSpec("player", "Player", icon, intent);

		// channel
		icon = R.drawable.ic_tab_channel;
		intent = new Intent().setClass(this, ChannelActivity.class);
		addNewTabSpec("channel", "Channel", icon, intent);

		// map
		icon = R.drawable.ic_tab_map;
		intent = new Intent().setClass(this, GeoActivity.class);
		addNewTabSpec("map", "Map", icon, intent);

		// rating
		icon = R.drawable.ic_tab_rating;
		intent = new Intent().setClass(this, RatingActivity.class);
		addNewTabSpec("rating", "Rating", icon, intent);

		Log.i(TAG, "Done creating tabs.");
	}

	/**
	 * creates a new TabSpec an adds it to the TabHost
	 * 
	 * @param tag
	 * @param label
	 * @param icon
	 * @param intent
	 * @return TabSpec
	 */
	private TabSpec addNewTabSpec(String tag, String label, int icon, Intent intent) {
		TabSpec spec = tabHost.newTabSpec(tag)
				.setIndicator(label, res.getDrawable(icon))
				.setContent(intent);
		tabHost.addTab(spec);
		Log.i(TAG, "Tag: " + tag + ", Label: " + label);
		return spec;
	}

	/**
	 * switches the TabHost to another tab
	 * 
	 * @param tab
	 */
	public void switchTab(int tabId) {
		tabHost.setCurrentTab(tabId);
	}

	/**
	 * switches the TabHost to the default tab
	 */
	public void switchToDefaultTab() {
		switchTab(TAB_DEFAULT);
	}
	
	/**
	 * updates the current weather conditions
	 * 
	 * @param location
	 */
	private void updateWeatherConditions(Location location) {
		Weather weather = application.getWeather();
		if (weather.isTimeToUpdate()) {
			List<WeatherUpdatedListener> listeners = application.getWeatherUpdatedListeners();
			new UpdateWeatherConditionsTask(location, weather, listeners).execute();
		}
	}
	
	/**
	 * gets the region the user is currently in
	 * 
	 * @param location
	 * @return
	 */
	private Region getRegion(Location location) {
		RegionHandler rHandler = application.getRegionHandler();
		for (Region r : rHandler.loadRegions(null, null, null, null)) {
			if (r.isOnThisRegion((float) location.getLatitude(), (float) location.getLongitude()) && r != ((Playmee) getApplication()).currentRegion) {
				return r;
			}
		}
		return null;
	}
	
	/**
	 * computes the playlist and starts playing
	 * 
	 * @param channel
	 */
	private void playChannel(Region region) {
		boolean gpsEnabled = application.gpsLocationProviderIsEnabled()
				|| application.networkLocationProviderIsEnabled();
		Weather weather = application.getWeather();
		
		Channel channel = region.getChannel();
		
		// if the current weather conditions should be considered
		// make sure that they were loaded before
		if (channel.isConsideringWeather()) {
			if (!gpsEnabled || weather.getCurrentWeather() == null) {
				// Toast.makeText(this, "Playing channel failed. Please start manually.", Toast.LENGTH_SHORT).show();
				return;
			}
		}
		
		// check if we are connected to the internet
		boolean hasNetworkConnetion = application.hasNetworkConnection();
		
		// if the current weather conditions should be considered
		// make sure that we have an internet connection
		if (channel.isConsideringWeather() && !hasNetworkConnetion) {
			// Toast.makeText(this, "Playing channel failed. Please start manually.", Toast.LENGTH_SHORT).show();
			return;
		}
		
		application.currentRegion = region;
		Toast.makeText(this, "Current region: " + region.getTitle(), Toast.LENGTH_SHORT).show();
		
		// start computing the playlist
		(new ComputePlaylistTask(application.getAccountHandler(),
				application.getPlaylistHandler(), channel, hasNetworkConnetion,
				weather, this)).execute();
	}
	
	@Override
	public void onPlaylistComputed(Playlist playlist) {
		// nothing can be played
		if (playlist == null) {
			Toast.makeText(this, "Playing channel failed. Please start manually.", Toast.LENGTH_SHORT).show();
			application.isStartingChannelInRegion = false;
			return;
		}
		
		PlaylistHandler pHandler = application.getPlaylistHandler();
		if (pHandler.getCurrentPlaylist() != playlist)
			pHandler.setCurrentPlaylist(playlist);
		
		// start playing and switch to the player tab
		startService(new Intent(MusicService.ACTION_STOP));
		startService(new Intent(MusicService.ACTION_PLAY)); // TODO
		switchTab(TAB_MAP);
		switchTab(TAB_CHANNEL);
		switchTab(TAB_PLAYER);
	}
}
